import type { ConversationFlow } from '../index'
import type { CommentInfo, QuoteNavigationConfig } from '../types'
import { ThemeVarService } from '../../../../../lib/abstract/style/theme_var/service'
import { PageHandler } from '../../../../../lib/page_handler'
import { ToolKit } from '../../../../../lib/utils/toolkit'

enum QuoteLinkClass {
  QuoteLink = 'quote-link',
  QuotedLink = 'quoted-link',
}

export class ConversationFlowUI {
  readonly name: string = 'ConversationFlowUI'
  readonly containerClass: string = 'navigation-container'
  readonly sequenceContainerClass: string = 'sequence-navigation'
  readonly quoteContainerClass: string = 'quote-navigation'
  private static instance: ConversationFlowUI
  private readonly themeVarService: ThemeVarService = ThemeVarService.getInstance()
  private readonly pageHandler: PageHandler = PageHandler.getInstance()
  clickEventListeners: Map<string, (e: JQuery.ClickEvent) => void> = new Map()
  readonly clickEventNamespace: string = 'click.quoteNav'

  constructor(private quoteInstance: ConversationFlow) {
  }

  /**
   * 获取单例实例
   */
  public static getInstance(quoteInstance: ConversationFlow): ConversationFlowUI {
    if (!ConversationFlowUI.instance) {
      ConversationFlowUI.instance = new ConversationFlowUI(quoteInstance)
    }
    return ConversationFlowUI.instance
  }

  /**
   * 渲染链接
   */
  renderLinks(config: QuoteNavigationConfig): void {
    this.quoteInstance.commentsMap.forEach((commentInfo) => {
      this.renderNavigationLinks(commentInfo, config)
    })
  }

  /**
   * 渲染导航链接
   */
  renderNavigationLinks(commentInfo: CommentInfo, config: QuoteNavigationConfig): void {
    const { quoteTargets, quotedBy, element } = commentInfo
    const { content, sequenceInsert } = config

    // 检查是否需要渲染任何导航
    const hasSequenceNav = this.shouldRenderSequenceNavigation(commentInfo)
    const hasQuoteNav = quoteTargets.length > 0 || quotedBy.length > 0

    if (!hasSequenceNav && !hasQuoteNav) {
      return // 没有任何导航需要渲染
    }

    const $navigationContainer = this.createNavigationContainer(element)
    this.quoteInstance.tracker.creation($navigationContainer)

    // 渲染上下导航
    if (hasSequenceNav) {
      this.renderSequenceNavigation(commentInfo, element.find(sequenceInsert))
    }

    // 渲染引用关系导航
    if (hasQuoteNav) {
      this.renderQuoteNavigation(commentInfo, $navigationContainer)
    }

    element.find(content).append($navigationContainer)
    ToolKit.browser.platform.markProjectElement($navigationContainer)
  }

  /**
   * 渲染上下导航
   */
  private renderSequenceNavigation(commentInfo: CommentInfo, element: JQuery<HTMLElement>): void {
    const { id, userNavigation } = commentInfo

    if (!userNavigation) {
      return
    }

    const previousComment = this.getPreviousUserComment(id)
    const nextComment = this.getNextUserComment(id)

    // 只有存在上一个或下一个评论时才渲染上下导航
    if (!previousComment && !nextComment) {
      return
    }

    const $sequenceNav = $(`
      <div class="${this.sequenceContainerClass}">
        <div class="nav-buttons">
          ${previousComment ? `<button class="nav-btn nav-previous" data-target-id="${previousComment.id}">上一条</button>` : ''}
          ${nextComment ? `<button class="nav-btn nav-next" data-target-id="${nextComment.id}">下一条</button>` : ''}
        </div>
      </div>
    `)

    element.after($sequenceNav)

    // 绑定事件
    this.bindSequenceNavigationEvents($sequenceNav)
    ToolKit.browser.platform.markProjectElement($sequenceNav)
  }

  /**
   * 绑定上下导航事件
   */
  private bindSequenceNavigationEvents($sequenceNav: JQuery<HTMLElement>): void {
    // 按钮点击事件
    $sequenceNav.find('.nav-btn').on('click', (e) => {
      e.preventDefault()
      e.stopPropagation()

      const $button = $(e.currentTarget)
      const targetId = $button.data('target-id')

      this.pageHandler.scrollToComment(targetId)
    })
  }

  /**
   * 渲染引用关系导航 - 引用在右，被引用在左
   */
  renderQuoteNavigation(commentInfo: CommentInfo, $navigationContainer: JQuery<HTMLElement>): void {
    const { quoteTargets, quotedBy } = commentInfo

    const $quoteNav = $(`
      <div class="${this.quoteContainerClass}">
        <div class="quoted-links-container">
          <div class="quoted-links"></div>
        </div>
        <div class="quote-links-container">
          <div class="quote-links"></div>
        </div>
      </div>
    `)

    const $quoteLinksContainer = $quoteNav.find('.quote-links')
    const $quotedLinksContainer = $quoteNav.find('.quoted-links')

    // 渲染引用链接（放在右侧）
    if (this.quoteInstance.config.showQuoteLinks && quoteTargets.length > 0) {
      quoteTargets.forEach((targetId) => {
        const targetComment = this.quoteInstance.commentsMap.get(targetId)
        if (targetComment) {
          const $link = this.createNavigationLink(
            targetId,
            targetComment.floorNumber,
            QuoteLinkClass.QuoteLink,
          )
          $quoteLinksContainer.append($link)
        }
      })
    }

    // 渲染被引用链接（放在左侧，按时间排序）
    if (this.quoteInstance.config.showQuotedByLinks && quotedBy.length > 0) {
      const sortedQuotedBy = quotedBy
        .map(id => this.quoteInstance.commentsMap.get(id))
        .filter(Boolean)
        .sort((a, b) => new Date(a!.timestamp).getTime() - new Date(b!.timestamp).getTime())
        .map(comment => comment!.id)

      sortedQuotedBy.forEach((quotedById) => {
        const quotingComment = this.quoteInstance.commentsMap.get(quotedById)
        if (quotingComment) {
          const $link = this.createNavigationLink(
            quotedById,
            quotingComment.floorNumber,
            QuoteLinkClass.QuotedLink,
          )
          $quotedLinksContainer.append($link)
        }
      })
    }

    // 如果引用链接容器为空，移除它
    if ($quoteLinksContainer.children().length === 0) {
      $quoteNav.find('.quote-links-container').remove()
    }

    // 如果被引用链接容器为空，移除它
    if ($quotedLinksContainer.children().length === 0) {
      $quoteNav.find('.quoted-links-container').remove()
    }

    // 如果两个容器都为空，不添加引用导航
    if ($quoteLinksContainer.children().length > 0 || $quotedLinksContainer.children().length > 0) {
      $navigationContainer.append($quoteNav)
    }
  }

  /**
   * 检查是否需要渲染上下导航
   */
  private shouldRenderSequenceNavigation(commentInfo: CommentInfo): boolean {
    const { userNavigation } = commentInfo

    if (!userNavigation)
      return false

    // 只有用户有多条评论时才显示上下导航
    return userNavigation.userCommentCount > 1
  }

  /**
   * 创建导航容器
   */
  private createNavigationContainer(element: JQuery<HTMLElement>): JQuery<HTMLElement> {
    const container = $(`.${this.containerClass}`, element)

    if (container.length > 0) {
      return container
    }

    return $(`
      <div class="${this.containerClass}">
      </div>
    `)
  }

  /**
   * 创建导航链接
   */
  private createNavigationLink(targetId: string, floorNumber: number, linkClass: QuoteLinkClass = QuoteLinkClass.QuoteLink): JQuery<HTMLElement> {
    const title = `${linkClass === QuoteLinkClass.QuoteLink ? `该条评论回复了第 ${floorNumber} 条评论` : `第 ${floorNumber} 条评论已回复该条评论`}`
    const linkId = `quote-link-${Date.now()}`
    const $link = $(`
      <a
      id="${linkId}"
      href="#${targetId}"
      class="${linkClass}"
      style="color: var(${this.themeVarService.default.text.secondary}) !important; border: 1px solid var(${this.themeVarService.default.border.colorNeutral}) !important;"
      title="${title}">
          #${floorNumber}
      </a>
    `)

    const clickHandler = (e: JQuery.ClickEvent) => {
      e.preventDefault()

      this.pageHandler.scrollToComment(targetId)
    }

    $link.off(this.clickEventNamespace as any).on(this.clickEventNamespace as any, clickHandler)
    this.clickEventListeners.set(linkId, clickHandler)

    return $link
  }

  /**
   * 获取同一用户上一条评论
   */
  getPreviousUserComment(commentId: string): CommentInfo | null {
    const comment = this.quoteInstance.commentsMap.get(commentId)

    if (!comment || !comment.userNavigation?.previousCommentId) {
      return null
    }

    const previousComment = this.quoteInstance.commentsMap.get(comment.userNavigation.previousCommentId)

    if (!previousComment) {
      return null
    }

    // 检查是否是连续评论
    if (previousComment.floorNumber === comment.floorNumber - 1) {
      return null // 如果是连续评论，不显示上一条导航
    }

    return previousComment
  }

  /**
   * 获取同一用户下一条评论
   */
  getNextUserComment(commentId: string): CommentInfo | null {
    const comment = this.quoteInstance.commentsMap.get(commentId)

    if (!comment || !comment.userNavigation?.nextCommentId) {
      return null
    }

    const nextComment = this.quoteInstance.commentsMap.get(comment.userNavigation.nextCommentId)

    if (!nextComment) {
      return null
    }

    // 检查是否是连续评论
    if (nextComment.floorNumber === comment.floorNumber + 1) {
      return null // 如果是连续评论，不显示下一条导航
    }

    return nextComment
  }
}
